package com.one.group.admin.controller;

import com.alibaba.excel.EasyExcel;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.one.group.admin.excel.ParkingSpaceData;
import com.one.group.admin.excel.ParkingSpaceDataReadListener;
import com.one.group.admin.mapper.OwnerMapper;
import com.one.group.admin.mapper.ParkingSpaceMapper;
import com.one.group.enums.ErrorCode;
import com.one.group.model.dto.BaseDeleteDto;
import com.one.group.model.dto.ParkingSpaceAddDto;
import com.one.group.model.dto.ParkingSpaceBindDto;
import com.one.group.model.dto.ParkingSpaceChargeBatchBindDto;
import com.one.group.model.dto.ParkingSpaceChargeBindDto;
import com.one.group.model.dto.ParkingSpaceChargeUnbindDto;
import com.one.group.model.dto.ParkingSpaceQueryDto;
import com.one.group.model.dto.ParkingSpaceUnbindDto;
import com.one.group.model.entity.ParkingSpace;
import com.one.group.model.vo.ParkingSpaceDetailVo;
import com.one.group.model.vo.ParkingSpaceListVo;
import com.one.group.model.vo.ParkingSpaceSearchVo;
import com.one.group.result.Result;
import com.one.group.service.ParkingSpaceService;
import com.one.group.utils.ResultUtil;
import com.one.group.utils.ThrowUtil;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.convert.Convert;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("parkingSpace")
@Tag(name = "车位管理接口")
public class ParkingSpaceController {
    @Autowired
    private ParkingSpaceService parkingSpaceService;

    @Autowired
    private ParkingSpaceMapper parkingSpaceMapper;
    @Autowired
    private OwnerMapper ownerMapper;


    /**
     * 查询车位列表,需要和收费标准表、车位-收费标准表、小区表连表查询
     * @param parkingSpaceQueryDto
     * @return 车位管理列表
     */
    @RequestMapping(value = "/list",method = RequestMethod.GET)
    @Operation(summary = "车位列表")
    public Result<PageInfo<ParkingSpaceListVo>> list(ParkingSpaceQueryDto parkingSpaceQueryDto){

        //1.分页条件
        PageHelper.startPage(parkingSpaceQueryDto.getPage(),parkingSpaceQueryDto.getLimit());

        List<ParkingSpaceListVo> list = parkingSpaceService.findParkingSpaceByQueryDto(parkingSpaceQueryDto);

        //3.分页结果
        PageInfo<ParkingSpaceListVo> pageInfo = new PageInfo<>(list);
        return ResultUtil.success(pageInfo);
    }

    /**
     * 添加车位
     * @param parkingSpaceAddDto
     * @return 添加结果
     */
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    @Operation(summary = "添加车位")
    public Result add(@Valid @RequestBody ParkingSpaceAddDto parkingSpaceAddDto, BindingResult bindingResult) {
        //1.校验
        if(bindingResult.hasErrors()){
            List<ObjectError> errors = bindingResult.getAllErrors();
            StringBuilder sb = new StringBuilder();
            errors.forEach(objectError -> {
                String message = objectError.getDefaultMessage();
                sb.append(message).append(",");
            });
            return ResultUtil.error(ErrorCode.ADD_ERROR.getCode(),sb.toString());
        }
        boolean result = parkingSpaceService.addParkingSpace(parkingSpaceAddDto);
        if (result) {
            return ResultUtil.success();
        } else {
            return ResultUtil.error(ErrorCode.ADD_ERROR.getCode(), "添加车位失败");
        }
    }

    /**
     * 删除车位
     * @param id 车位ID
     * @return 删除结果
     */
    @GetMapping("/delete")
    @Operation(summary = "删除车位")
    public Result delete(Long id){
        ThrowUtil.throwIf(id==null, ErrorCode.PARAMS_ERROR);
        boolean result = parkingSpaceService.deleteParkingSpace(id);
        if (result) {
            return ResultUtil.success();
        } else {
            return ResultUtil.error(ErrorCode.DELETE_ERROR.getCode(), "删除车位失败");
        }
    }

    /**
     * 批量删除车位
     * @param baseDeleteDto 批量删除DTO
     * @return 删除结果
     */
    @PostMapping("/deleteBatch")
    @Operation(summary = "批量删除车位")
    public Result deleteBatch(@RequestBody BaseDeleteDto baseDeleteDto) {
        ThrowUtil.throwIf(baseDeleteDto == null || baseDeleteDto.getIds() == null || baseDeleteDto.getIds().isEmpty(), 
                         ErrorCode.PARAMS_ERROR, "参数不能为空");
        boolean result = parkingSpaceService.batchDeleteParkingSpaces(baseDeleteDto.getIds());
        if (result) {
            return ResultUtil.success();
        } else {
            return ResultUtil.error(ErrorCode.DELETE_ERROR.getCode(), "批量删除车位失败");
        }
    }

    /**
     * 绑定车辆到车位
     * @param bindDto 绑定信息
     * @return 绑定结果
     */
    @PostMapping("/bindVehicle")
    @Operation(summary = "绑定车辆到车位")
    public Result bindVehicle(@Valid @RequestBody ParkingSpaceBindDto bindDto) {
        boolean result = parkingSpaceService.bindVehicle(bindDto);
        if (result) {
            return ResultUtil.success();
        } else {
            return ResultUtil.error(ErrorCode.OPERATION_ERROR.getCode(), "绑定车辆失败");
        }
    }

    /**
     * 解绑车辆与车位
     * @param unbindDto 解绑信息
     * @return 解绑结果
     */
    @PostMapping("/unbindVehicle")
    @Operation(summary = "解绑车辆与车位")
    public Result unbindVehicle(@Valid @RequestBody ParkingSpaceUnbindDto unbindDto) {
        boolean result = parkingSpaceService.unbindVehicle(unbindDto);
        if (result) {
            return ResultUtil.success();
        } else {
            return ResultUtil.error(ErrorCode.OPERATION_ERROR.getCode(), "解绑车辆失败");
        }
    }

    /**
     * 查询车位详情
     * @param id 车位ID
     * @return 车位详情
     */
    @GetMapping("/detail")
    @Operation(summary = "查询车位详情")
    public Result<ParkingSpaceDetailVo> getDetail(Long id) {
        ThrowUtil.throwIf(id == null, ErrorCode.PARAMS_ERROR);
        ParkingSpaceDetailVo detail = parkingSpaceService.getParkingSpaceDetail(id);
        if(detail == null) {
            return ResultUtil.error(ErrorCode.NOT_FOUND_ERROR.getCode(), "车位不存在");
        }
        return ResultUtil.success(detail);
    }

    /**
     * 修改车位信息
     * @param parkingSpace 修改信息
     * @return 修改结果
     */
    @RequestMapping(value = "/update",method = RequestMethod.POST)
    @Operation(summary = "修改车位信息")
    public Result update(@RequestBody ParkingSpace parkingSpace){

        //1.调用service进行修改
        boolean result = parkingSpaceService.updateById(parkingSpace);
        //2.封装返回结果
        if(result){
            return ResultUtil.success();
        }
        return ResultUtil.error(ErrorCode.UPDATE_ERROR.getCode(), "修改车位失败");

    }

    /**
     * 根据id查询车位信息
     * @param id 车位id
     * @return 车位信息
     */
    @GetMapping("/findById")
    @Operation(summary = "根据id查询车位信息")
    public Result find(@RequestParam Long id){
        //1.参数校验
        ThrowUtil.throwIf(id == null, ErrorCode.NOT_FOUND_ERROR);
        return ResultUtil.success(parkingSpaceService.getById(id));
    }

    /**
     * 绑定收费标准到车位
     * @param bindDto 绑定信息
     * @return 绑定结果
     */
    @PostMapping("/bindChargeStandard")
    @Operation(summary = "绑定收费标准到车位")
    public Result bindChargeStandard(@Valid @RequestBody ParkingSpaceChargeBindDto bindDto) {
        boolean result = parkingSpaceService.bindChargeStandard(bindDto);
        if (result) {
            return ResultUtil.success();
        } else {
            return ResultUtil.error(ErrorCode.OPERATION_ERROR.getCode(), "绑定收费标准失败");
        }
    }

    /**
     * 批量绑定收费标准到车位
     * @param batchBindDto 批量绑定信息
     * @return 绑定结果
     */
    @PostMapping("/batchBindChargeStandard")
    @Operation(summary = "批量绑定收费标准到车位")
    public Result batchBindChargeStandard(@Valid @RequestBody ParkingSpaceChargeBatchBindDto batchBindDto) {
        boolean result = parkingSpaceService.batchBindChargeStandard(batchBindDto);
        if (result) {
            return ResultUtil.success();
        } else {
            return ResultUtil.error(ErrorCode.OPERATION_ERROR.getCode(), "批量绑定收费标准失败");
        }
    }

    /**
     * 解除车位与收费标准的绑定
     * @param unbindDto 解除绑定信息
     * @return 解除绑定结果
     */
    @PostMapping("/unbindChargeStandard")
    @Operation(summary = "解除车位与收费标准的绑定")
    public Result unbindChargeStandard(@Valid @RequestBody ParkingSpaceChargeUnbindDto unbindDto) {
        boolean result = parkingSpaceService.unbindChargeStandard(unbindDto);
        if (result) {
            return ResultUtil.success();
        } else {
            return ResultUtil.error(ErrorCode.OPERATION_ERROR.getCode(), "解除绑定失败");
        }
    }

    /**
     * 批量导入车位信息
     * @param file Excel文件
     * @return 导入结果
     */
    @PostMapping("/import")
    @Operation(summary = "批量导入车位信息")
    public Result<String> importParkingSpaces(@RequestParam("file") MultipartFile file) throws IOException {
        // 获取当前租户ID
        Long tenantId = Convert.toLong(StpUtil.getExtra("tenant_id"));
        
        // 使用EasyExcel读取文件
        EasyExcel.read(file.getInputStream(), ParkingSpaceData.class,
                new ParkingSpaceDataReadListener(parkingSpaceService, parkingSpaceMapper, tenantId))
                .sheet()
                .doRead();
        
        return ResultUtil.success("导入成功");
    }

    /**
     * 导出车位Excel模板
     * @param response HTTP响应
     */
    @GetMapping("/exportTemplate")
    @Operation(summary = "导出车位Excel模板")
    public void exportTemplate(HttpServletResponse response) throws IOException {
        // 设置响应头
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        
        // 设置文件名
        String fileName = URLEncoder.encode("车位导入模板", StandardCharsets.UTF_8).replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        
        // 创建示例数据
        List<ParkingSpaceData> templateData = new ArrayList<>();
        
        // 添加示例行
        ParkingSpaceData example = new ParkingSpaceData();
        example.setSpaceNo("10001");
        example.setCellName("中山国际");
        example.setTypeName("产权车位/公共车位/租赁车位/访客车位/其他");
        example.setStatusName("空置/自用/出租/出售/占用/报废");
        example.setArea(12.0);
        example.setLocation("A区1层");
        example.setRemark("示例备注");
        templateData.add(example);
        
        // 写入Excel
        EasyExcel.write(response.getOutputStream(), ParkingSpaceData.class)
                .sheet("车位导入模板")
                .doWrite(templateData);
    }

    /**
     * 根据车位编号模糊搜索车位
     * @param spaceNo 车位编号（支持模糊搜索）
     * @param cellId 小区ID
     * @return 车位搜索结果列表
     */
    @GetMapping("/search")
    @Operation(summary = "车位搜索")
    public Result<List<ParkingSpaceSearchVo>> searchParkingSpaces(@RequestParam String spaceNo, @RequestParam Long cellId) {
        List<ParkingSpaceSearchVo> result = parkingSpaceService.searchParkingSpacesBySpaceNo(spaceNo, cellId);
        return ResultUtil.success(result);
    }
    //绑定住户
    @PostMapping("/bindOwner")
    @Operation(summary = "绑定住户")
    public Result bindOwner(@RequestParam Long id, @RequestParam Long ownerId) {
        boolean result = parkingSpaceService.bindOwner(id, ownerId);
        if (result) {
            return ResultUtil.success();
        } else {
            return ResultUtil.error(ErrorCode.OPERATION_ERROR.getCode(), "绑定住户失败");
        }
    }
    //解绑住户
    @PostMapping("/unbindOwner")
    @Operation(summary = "解绑住户")
    public Result unbindOwner(@RequestParam Long id) {
        boolean result = parkingSpaceService.unbindOwner(id);
        if (result) {
            return ResultUtil.success();
        } else {
            return ResultUtil.error(ErrorCode.OPERATION_ERROR.getCode(), "解绑住户失败");
        }
    }


}
